#include "pool.h"
Pool* Pool::PollInstance = nullptr;
task_t   Pool::Task_fun  = nullptr;    

bool operator==(const TaskNode& lhs, const TaskNode& rhs)
{
    return (lhs.do_task == rhs.do_task) && (lhs.arg == rhs.arg);

}

unsigned int Pool::Get_Active(void) const
{
    return this->ActiveTread;
}
unsigned int Pool::Get_TaskCount(void) const
{
    return this->CurTask;
}
unsigned int Pool::Get_MaxTask(void) const
{
    return this->MaxTask;
}
unsigned int Pool::Get_MaxThread(void) const
{
    return this->MaxThread;
}
unsigned int Pool::Get_MinThread(void) const
{
    return this->MinThread;
}

void Pool::Set_MaxTask(unsigned int num)
{
    pthread_mutex_lock(&(this->Mutex));
    this->MaxTask = num;
    pthread_mutex_unlock(&(this->Mutex));

}
void Pool::Set_MaxThread(unsigned int num)
{
    pthread_mutex_lock(&(this->Mutex));
    this->MaxThread = num;
    pthread_mutex_unlock(&(this->Mutex));
}
void Pool::Set_MinThread(unsigned int num)
{
    pthread_mutex_lock(&(this->Mutex));
    this->MinThread = num;
    pthread_mutex_unlock(&(this->Mutex));
}


Pool* Pool::GetInstance(unsigned int active,unsigned int max_task,unsigned int max_thread,unsigned int min_thread)
{

    if(PollInstance == nullptr)
    {
        PollInstance = new Pool(active,max_task,max_thread,min_thread);
    }
    return PollInstance;
}

void handler(void*arg)
{
    cout << "Thread cancellation releases the mutex lock :" <<pthread_self() << endl;

    pthread_mutex_unlock((pthread_mutex_t *)arg);
}

void* ThreadWorkFun(void* arg)
{
    Pool* pool = static_cast<Pool*>(arg);

    TaskNode task;
    
    // 这里可以调用队列取任务并执行
    while (true)
    {


        // 写遗书（准备好退出处理函数，防止在持有一把锁的状态中死去）
        pthread_cleanup_push(handler,&(pool->Mutex));

        // 试图持有互斥锁
        pthread_mutex_lock(&(pool->Mutex));

        while(pool->TaskLists.empty())
            pthread_cond_wait(&(pool->Cond),&(pool->Mutex));
        // 取出任务
        task = pool->TaskLists.front();
        pool->TaskLists.pop_front();
        --(pool->CurTask);
        pthread_mutex_unlock((&(pool->Mutex)));

        // 销毁遗书（将备用的退出处理函数弹出，避免占用内存）
        pthread_cleanup_pop(0);

        // 为避免在执行任务期间被强制终止，可先屏蔽取消指令
        pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);

        if(task.do_task != NULL)
            task.do_task(task.arg);

        pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);

    }
    return nullptr;

}


/**
 * @brief Construct a new Pool:: Pool object 初始化poll
 * 
 * @param max_task          最大任务数量
 * @param max_thread        最大线程数量
 * 
 * @note 最小的线程数量是一个
 */
Pool::Pool(unsigned int active,unsigned int max_task,unsigned int max_thread,unsigned int min_thread):MaxTask(max_task),MaxThread(max_thread),MinThread(min_thread)
{
    
    // 初始化互斥锁 条件变量
    pthread_mutex_init(&(this->Mutex),NULL);
    pthread_cond_init(&(this->Cond),NULL);

    //判断线程是否大于0
    active = active > this->MinThread ? active : MinThread;

    this->Add_Thread(active);

}

Pool::~Pool()
{
    // 回收资源

    cout << "~Pool" << endl;

    this->Set_MinThread(0);
    this->Del_Thread(this->ActiveTread);
    pthread_mutex_destroy(&(this->Mutex));
    pthread_cond_destroy(&(this->Cond));

    

    cout << "回收资源完成" << endl;

}

bool Pool::Set_TaskFun(task_t taskfun)
{
    pthread_mutex_lock(&(this->Mutex));
    Pool::Task_fun = taskfun;
    pthread_mutex_unlock(&(this->Mutex));

    return true;

}



unsigned int Pool::Add_Thread(unsigned int num)
{

    pthread_t thread_id;
    int res;
    unsigned int pos;
    for(pos = 0 ; pos < num; pos++)
    {   
        //判断当前是否超过最大数量

        if(this->ActiveTread > MaxTask)
        {
            cout << "The maximum number of threads has been reached."<< endl;
            break;
        }

        res = pthread_create(&thread_id,NULL,ThreadWorkFun,this);
        if(res == 0)
        {
            this->ActiveTread++;
            this->ThreadLists.push_back(thread_id);
            cout << "the create thread is " << thread_id << endl;
        }
            
        else
            cout << "create thread fail\r\n" << endl;
    }

    cout << "The number of threads created is: " << pos << endl;

    return pos;

}

/**
 * @brief   至少保留一个活跃线程
 * 
 * @param num 
 * @return unsigned int 
 */
unsigned int Pool::Del_Thread(unsigned int num)
{
    
    unsigned int delCount;

    /*

        1.    cur - min > num    10-1 > 5  5
        2.    cur - min = num    6-1  = 5  5
        3.    cur - min < num    5-1  < 5  cur-min
    */

    delCount = ((this->ActiveTread - this->MinThread) >= num ? num : (this->ActiveTread - this->MinThread));

    cout << "delCount : " << delCount <<endl;


    for(unsigned int  pos = 0;pos < delCount; pos++)
    {
        pthread_cancel(this->ThreadLists.back());
        if(pthread_join(this->ThreadLists.back(),NULL) == 0)
            cout << "delete thread is" << this->ThreadLists.back() << endl;
        this->ThreadLists.pop_back();

        pthread_mutex_lock(&(this->Mutex));
        this->ActiveTread--;
        pthread_mutex_unlock(&(this->Mutex));
        
    }

    return delCount;

}


bool Pool::Add_Task(int fd)
{   
    if(this->CurTask > this->MaxTask)
    {
        cout << "The maximum number of tasks has been reached." << endl;
        return false;
    }
    else
    {
        TaskNode Tasknode;
        Tasknode.do_task = Pool::Task_fun;
        Tasknode.arg = new int(fd);

        pthread_mutex_lock(&(this->Mutex));
        this->TaskLists.push_back(Tasknode);
        (this->CurTask++);
        pthread_mutex_unlock(&(this->Mutex));
        pthread_cond_signal(&(this->Cond));

    }
    return true;
}

bool Pool::Add_Task(TaskNode& tasknode)
{
    if(this->CurTask > this->MaxTask)
    {
        cout << "The maximum number of tasks has been reached." << endl;
        return false;
    }
    else
    {
        pthread_mutex_lock(&(this->Mutex));
        this->TaskLists.push_back(tasknode);
        (this->CurTask++);
        pthread_mutex_unlock(&(this->Mutex));
        pthread_cond_signal(&(this->Cond));
        return true;
    }

}

bool Pool::Del_Task(int fd)
{
    bool flag = false;
    pthread_mutex_lock(&(this->Mutex));
    auto it = find_if(this->TaskLists.begin(),this->TaskLists.end(),
                        [fd](TaskNode Node)->bool
                        {
                            if((*(int*)(Node.arg) == fd ) || Node.do_task == Task_fun)
                            {
                                return true;
                            }
                            return false;
                        }
                    );
    if(it != this->TaskLists.end())
    {
        this->TaskLists.erase(it);
        this->CurTask--;
        flag = true;
    }
    pthread_mutex_unlock(&(this->Mutex));
    
    return flag;
}

bool Pool::Del_Task(const TaskNode& tasknode)
{
    pthread_mutex_lock(&(this->Mutex));
    auto it = find(this->TaskLists.begin(),this->TaskLists.end(),tasknode);
    if(it != this->TaskLists.end())
    {
        this->TaskLists.erase(it);
        this->CurTask--;
    }
    pthread_mutex_unlock(&(this->Mutex));

    return true;
}
unsigned int Pool::Del_Task(unsigned int num)
{   

    unsigned int DelTask;

    /*
        1. DelTask > num       num;
        2. DelTask = num       num;
        3. DelTask < num       DelTask;

    */
    pthread_mutex_lock(&(this->Mutex));

    DelTask = (this->CurTask >= num) ? num : this->CurTask;
    cout << "DelTask: " << DelTask << endl;

    for(unsigned int pos = 0; pos < DelTask; pos++)
    {
        this->TaskLists.pop_back();
        this->CurTask--;
        cout << pos << endl;

    }
    pthread_mutex_unlock(&(this->Mutex));

    return DelTask;
}


void Pool::Print_info(void)
{
    cout << "pool info" << endl;
    cout << "pool.Get_Active(): "   << this->Get_Active() << endl;
    cout << "pool.Get_TaskCount():" << this->Get_TaskCount() << endl;
    cout << "pool.Get_MaxTask():"   << this->Get_MaxTask() << endl;
    cout << "pool.Get_MaxThread():" << this->Get_MaxThread() << endl;
    cout << "pool.Get_MinThread():" << this->Get_MinThread() << endl;

}